package org.finegold.core.netty.core.websocket;

import io.netty.channel.ChannelHandler;
import io.netty.channel.ChannelInitializer;
import io.netty.channel.ChannelPipeline;
import io.netty.channel.socket.SocketChannel;
import io.netty.handler.codec.http.HttpObjectAggregator;
import io.netty.handler.codec.http.HttpServerCodec;
import io.netty.handler.codec.http.websocketx.WebSocketServerProtocolHandler;
import io.netty.handler.stream.ChunkedWriteHandler;
import org.finegold.core.netty.props.ServerProperties;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

import java.lang.reflect.Constructor;
import java.lang.reflect.InvocationTargetException;
import java.util.List;

/**
 * WebSocket服务器初始化器,此类用于构建Netty处理链
 * @author songkaikai
 * @since 2021/1/21
 */
public class WebSocketServerInitializer extends ChannelInitializer<SocketChannel> {

    private final Logger logger = LoggerFactory.getLogger(WebSocketServerInitializer.class);

    private final ServerProperties serverProperties;

	public WebSocketServerInitializer(ServerProperties serverProperties) {
		this.serverProperties = serverProperties;
	}

    @Override
    protected void initChannel(SocketChannel socketChannel) throws Exception {
        //获取通道链
        ChannelPipeline pipeline = socketChannel.pipeline();
        //组装链
        pipeline.addLast(new HttpServerCodec())
                .addLast(new ChunkedWriteHandler())
                .addLast(new HttpObjectAggregator(serverProperties.getMaxContentLength()))
				.addLast(resolveHandler(serverProperties.getChannelHandlers()))
                .addLast(new WebSocketServerProtocolHandler(serverProperties.getWsUrl()))
				;

    }

    /**
     * 解析处理器
     * @param channelHandlers 需要被实例化的通道处理器
     * @return 通道处理器数组
     * @throws IllegalAccessException 非法访问异常
     * @throws InstantiationException 实例化异常
     */
    private ChannelHandler[] resolveHandler(List<Class<? extends ChannelHandler>> channelHandlers) throws IllegalAccessException, InstantiationException, NoSuchMethodException, InvocationTargetException {
        int size = channelHandlers.size();
        // 警告检查
        if(size == 1 && (channelHandlers.get(0).isAssignableFrom(DefaultChannelHandler.class))){
            logger.warn("=================>请自定义ChannelHandler并在配置文件中配置!<===================");
        }
        //创建返回的处理器数组
        ChannelHandler[] chs = new ChannelHandler[size];
        for (int i = 0; i < size; i++) {
            Class<? extends ChannelHandler> cls = channelHandlers.get(i);
            //获取无参构造方法
            Constructor<? extends ChannelHandler> constructor = cls.getConstructor();
            //无参实例化
            chs[i] = constructor.newInstance();
        }
        return chs;
    }
}
